package demo.java.lang;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OSCommandExecuter {

	private static Logger logger = LoggerFactory.getLogger(OSCommandExecuter.class);

	public void executeCommand(String command) throws Exception {
		Process process = null;

		try {
			process = Runtime.getRuntime().exec(command);
			process.waitFor();
		} finally {
			if (process != null) {
				process.destroy();
			}
		}
	}

	private List<String> process(final Process process) throws Exception {
		final List<String> result = Collections.synchronizedList(new ArrayList<String>());
		// 获取命令执行结果, 有两个结果: 正常的输出 和 错误的输出（PS: 子进程的输出就是主进程的输入）
		// 防止子进程刷满缓冲区，死锁，异步读取缓冲区
		try {
			new Thread() {
				@Override
				public void run() {
					BufferedReader buffIn = null;
					try {
						buffIn = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
						String line = null;
						while ((line = buffIn.readLine()) != null) {
							result.add(line);
						}
					} catch (Exception e) {
						logger.error("process getInputStream error", e);
					} finally {
						closeStream(buffIn);
					}

				}
			}.start();
			new Thread() {
				@Override
				public void run() {
					BufferedReader buffError = null;
					try {
						buffError = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
						String line = null;
						while ((line = buffError.readLine()) != null) {
							result.add(line);
						}
					} catch (Exception e) {
						logger.error("process getErrorStream error", e);
					} finally {
						closeStream(buffError);
					}

				}
			}.start();
			process.waitFor();
		} finally {
			// 销毁子进程
			if (process != null) {
				process.destroy();
			}
		}
		// 返回执行结果
		return result;
	}

	public List<String> executeCommandAndReturn(String command) throws Exception {
		Process process = Runtime.getRuntime().exec(command);
		return process(process);
	}

	public List<String> executeCommandAndReturn(String[] cmdarray) throws Exception {
		// 执行命令, 返回一个子进程对象（命令在子进程中执行）
		Process process = Runtime.getRuntime().exec(cmdarray);
		return process(process);
	}

	private static void closeStream(Closeable stream) {
		if (stream != null) {
			try {
				stream.close();
			} catch (Exception e) {
				logger.error("closeStream {} error:", stream, e);
			}
		}
	}

}
